revision:
There are several of these rules like @media, @import, @font-face, and more.
The unique identifier is the @mark that comes before these rules. The at sign, '@' is followed by an identifier and includes everything up to the next semicolon ';' , or the next CSS block, whichever comes first.
These rules can be divided into two groups: general rules and nesting rules.
General CSS at-rules need to be placed on top of the stylesheet, before all the other CSS attributes and properties, because they are defining the general settings of the CSS rules and will not be overwritten by other rules.
@charset "utf-8";
There are other ways of handling charset, like placing it on the HTTP header, but there are certain use cases for declaring it in CSS. For example, when we are using non-ASCII characters for the content property, the browser has different ways of figuring out the character encoding: setting it in the calling HTML file, or the server might set content type with a certain character encoding, in the response header.
So in most cases, this is managed, but in case the encoding of the calling or returned HTML is different from a certain stylesheet, then @charset needs to be declared in the CSS file.
Example: @charset
@charset "UTF-8"; h1::before { content: "@charset "; } q { color: blue; } q::before { content: "∅ "; } q::after { content: " ∅"; }
So when parsing the CSS file and encountering a @import rule, the browser makes an HTTP request to fetch the external stylesheet and include its CSS properties right where the @import rule is declared.
Since this rule was built to help developers include stylesheets from other sources, it is not possible to include it within any of the conditional group at-rules like @media, @page, and @document.
Example: @import - wrong usage
/* iPhone in Portrait and Landscape */ @media only screen{ @import 'custom.css'; }
However, we can specify
Example: @import
@import 'custom.css' screen and (orientation:landscape);
Even though there are more sophisticated concepts like "SMACSS", there could be potential use cases for this rule in CSS.
The @namespace rule helps apply scoping for CSS that mix styles from different XML namespaces. Examples of XML namespaces are HTML, SVG, MathML, XLink, etc. This way, there will be no styling collisions between elements from different namespaces.
These are a subset of CSS at-rules that store a subset of additional statements within them, some of which might be conditional to a specific situation. They usually follow up after the general rules.
This feature is deprecated and no longer recommended.
This page-based style customization comes in different forms:
You can specify the rules for a specific URL:
Example: @document - url
@document url(https://example.com/)
You can specify the rules for pages that their URLs start with:
Example: @document - url
@document url-prefix(https://example.com/index)
You can specify the rules on a domain level and for all the pages related to it:
example: @document - domain level
@document domain(example.com)
You can also specify the rules for a predefined regex pattern you defined for more control:
example: @document - url
@document regexp("https:.*")
@font-face is a nested rule, and with it, you get different properties for defining the font:
ascent-override : defines the ascent metric for the font. The ascent metric is the height above the baseline that CSS uses to lay out line boxes in an inline formatting context.
Syntax: {ascent-override: normal | percentage;}
descent-override : defines the descent metric for the font. The descent metric is the height below the baseline that CSS uses to lay out line boxes in an inline formatting context.
Syntax: {descent-override: normal | percentage;}
font-display : determines how a font face is displayed based on whether and when it is downloaded and ready to use.
Syntax: {font-display: auto | block | swap | fallback | optional;}
font-family : specifies a name that will be used as the font face value for font properties. You get access to an identifier name for your custom font when and if it is downloaded and available to be used.
Syntax: {font-family: "family-name";}
Example: @font-face - font-family
@font-face { font-family: "CustomFont"; } // Possible usage p { font-family: 'CustomFont'; }
font-stretch : a font-stretch value. Accepts two values to specify a range that is supported by a font-face, for example "font-stretch: 50% 200%;"
Syntax: {font-stretch: ultra-condensed | extra-condensed | condensed | semi-condensed | normal | semi-expanded | expanded | extra-expanded | ultra-expanded | percentage ;}
font-style : a font-style value. Accepts two values to specify a range that is supported by a font-face, for example "font-style: oblique 20deg 50deg;"
Syntax: {font-style: normal | italic | oblique | oblique with angle (30deg) | oblique with angle range (30deg 50deg);}
font-weight : a font-weight value. Accepts two values to specify a range that is supported by a font-face, for example "font-weight: 100 400;"
Syntax: {font-weight: normal | bold | number | multiple values;}
font-feature-settings : allows control over advanced typographic features in OpenType fonts.
font-variation-settings : allows low-level control over OpenType or TrueType font variations, by specifying the four letter axis names of the features to vary, along with their variation values.
Syntax: {font-variation-settings: normal | <string> <number>;}
line-gap-override : defines the line gap metric for the font.
Syntax: {line-gap-override: normal | percentage;}
size-adjust : defines a multiplier for glyph outlines and metrics associated with this font. This makes it easier to harmonize the designs of various fonts when rendered at the same font size.
Syntax: {size-adjust: percentage;}
src : specifies references to font resources including hints about the font format and technology. It is required for the @font-face rule to be valid. You define the source of the font data. The font data can come from an external source using url() or local one using local(). This way, if the font is not available locally in the site directory or user system, it will be downloaded from the external source. Additionally, you can pass a format parameter, to hint toward the format of the defined font.
Syntax: {src: url() | format() | tech() | local(<font-face-name>) | <font-face-name>;}
Example: @font-face - src
@font-face { font-family: 'Helvetica'; src: url('Helvetica') format('woff'), local('Helvetica.woff') format('woff'); }
unicode-range : the range of Unicode code points to be used from the font.
With the CSS rules applied within @keyframes rule, we define CSS rules that need to be applied when the CSS animation name attached to the @keyframe rule is applied to an element.
Syntax:
@keyframes slidein { from { transform: translateX(0%); } to { transform: translateX(100%); } }
Values:
custom-ident : a name identifying the keyframe list. This must match the identifier production in CSS syntax.
from : a starting offset of 0%.
to : an ending offset of 100%.
percentage : a percentage of the time through the animation sequence at which the specified keyframe should occur.
Example: @keyframes
// CSS @keyframes ANIMATION-NAME { 0% { opacity: 0; } 100% { opacity: 1; } } // OR @keyframes ANIMATION-NAME { from { opacity: 0; } to { opacity: 1; } }
This is mainly used for responsive design, so developers can style elements at different window sizes that tend to resemble common mobile, tablet, and desktop devices.
Syntax:
/* At the top level of your code */ @media screen and (min-width: 900px) { article { padding: 1rem 3rem; } } /* Nested within another conditional at-rule */ @supports (display: flex) { @media screen and (min-width: 900px) { article { display: flex; } } }
Example: @media
#box { background-color: green; } @media only screen and (max-width: 600px) { #box { background-color: yellow; } }
This rule tests whether a browser supports a feature, then applies the styles for those elements if the condition is met.
The @supports "CSS at-rule" let you specify declarations that depend on a browser's support for one or more specific CSS features. This is called a "feature query" and the rule may be placed at the top level of your code or nested inside any other "conditional group at-rule".
The supports condition consists of one or more "name-value pairs" combined by conjunctions (and), disjunctions (or), and/or negations (not). Precedence of operators can be defined with parentheses.
Syntax:
@supports (<supports-condition>) { /* If the condition is true, use the CSS in this block. */ } //combined conditions @supports (<<supports-condition>) and (<supports-condition>) { /* If both conditions are true, use the CSS in this block. */ }
@supports (display: grid) { .site-content { display: grid; } }
@supports not (display: flex) { .el { display: table; /* ... */ } }
@supports (display: grid) { .photo-layout { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); grid-gap: 2rem; } }
/* Check one supported condition */ @supports (display: flex) { .module { display: flex; } } /* Check multiple conditions */ @supports (display: flex) and (-webkit-appearance: checkbox) { .module { display: flex; } }
It specifically contains pseudo-elements for styling the ":first page" as well as the ":left" and ":right" margins of the page.
Syntax:
/* Targets all the pages */ @page { size: 8.5in 9in; margin-top: 4in; } /* Targets all even-numbered pages */ @page :left { margin-top: 4in; } /* Targets all odd-numbered pages */ @page :right { size: 11in; margin-top: 4in; } /* Targets all selectors with `page: wide;` set */ @page wide { size: a4 landscape; }
Example: @page
@page :first { margin: 1in; }
A @counter-style rule defines how to convert a counter value into a string representation.n (at candidate recommendation stage)
The initial version of CSS defined a set of useful counter styles (see: list-style-type property). However, although more styles were added to this set of predefined styles over the years, this system proved too restrictive to fulfill the needs of worldwide typography. The @counter-style at-rule addresses this shortcoming in an open-ended manner, by allowing authors to define their own counter styles when the pre-defined styles aren't fitting their needs.
Example: @counter-style
@counter-style thumbs { system: cyclic; symbols: "\1F44D"; suffix: " "; } ul { list-style: thumbs; }
The @font-feature-values at-rule may be used either at the top level of your CSS or inside any CSS conditional-group at-rule.
It allows developers to explicitly define their CSS custom properties, allowing for property type checking, setting default values, and define whether a property can inherit values or not.
Feature queries are created using the CSS at-rule @supports, and are useful as they give web developers a way to test to see if a browser has support for a certain feature, and then provide CSS that will only run based on the result of that test.
CSS feature queries are part of the "CSS Conditional Rules module", which also contains the media query @media rule.
Feature queries behave in a similar way to media queries. The difference is that with a media query you are testing something about the environment, in which the web page is running. With feature queries you are testing browser support for CSS features.
Syntax: a feature query consists of the @supports rule, followed by the property name and value you would like to test for. You may not test for a bare property name such as display; the rule requires a property name and a value.
syntax: @supports (property: value) { CSS rules to apply }
The "@supports at-rule" associates a block of statements with a "supports condition".
The supports condition consists of one or more name-value pairs combined by conjunctions (and), disjunctions (or), and/or negations (not).
Precedence of operators can be defined with parentheses.
Declaration syntax: the most basic supports condition is a simple declaration (a property name followed by a value, separated by a colon). The declaration must be surrounded by parentheses.
the following example returns true if the browser's "transform-origin" property considers 5% 5% valid:
@supports (transform-origin: 5% 5%) {}
Function syntax: the second basic supports condition is a supports function, the syntax for these is supported by all browsers, but the functions themselves are still being standardized.
Tests if the browser supports the tested selector syntax. The following example returns true if the browser supports the child combinator:
@supports selector(A > B) {}
The "@supports CSS at-rule" lets you specify declarations that depend on a browser's support for one or more specific CSS features. This is called a feature query. The rule may be placed at the top level of your code or nested inside any other "conditional group at-rule".
Example : @supports
@supports (display: grid) { div { display: grid; } }
Example: @supports not
@supports not (display: grid) { div { float: right; } }
In JavaScript, @supports can be accessed via the CSS object model interface "CSSSupportsRule".
The "not" operator can precede any expression to create a new expression, resulting in the negation of the original one.
The following example returns true if the browser's transform-origin property doesn't consider 10em 10em 10em valid:
@supports not (transform-origin: 10em 10em 10em) {}
As with any operator, the "not" operator can be applied to a declaration of any complexity.
the following examples are both valid:
@supports not (not (transform-origin: 2px)) {} @supports (display: grid) and (not (display: inline-grid)) {}
The "and" operator creates a new expression from the conjunction of two shorter expressions. It returns true only if both of the shorter expressions are also true.
the following example returns true if and only if the two shorter expressions are simultaneously true:
@supports (display: table-cell) and (display: list-item) {}
Multiple conjunctions can be juxtaposed without the need of more parentheses.
the following are both equivalent:
@supports (display: table-cell) and (display: list-item) and (display:contents) {} @supports (display: table-cell) and ((display: list-item) and (display:contents)) {}
The "or" operator creates a new expression from the disjunction of two shorter expressions. It returns true if one or both of the shorter expressions is also true.
the following example returns true if at least one of the two shorter expressions is true:
@supports (transform-style: preserve) or (-moz-transform-style: preserve) {}
Multiple disjunctions can be juxtaposed without the need of more parentheses.
the following are both equivalent:
@supports (transform-style: preserve) or (-moz-transform-style: preserve) or (-o-transform-style: preserve) or (-webkit-transform-style: preserve) {} @supports (transform-style: preserve-3d) or ((-moz-transform-style: preserve-3d) or ((-o-transform-style: preserve-3d) or (-webkit-transform-style: preserve-3d))) {}
Note: When using both "and" and "or" operators, the parentheses must be used to define the order in which they apply. Otherwise, the condition is invalid and the whole rule is ignored.
<div> <div class="box" style="margin-left:5vw;">If your browser supports row-gap, the text and border will be red.</div> </div> <style> .box {border: 0.5vw solid blue; color: blue;} @supports (row-gap: 1vw) { .box {border: 0.5vw solid red; color: red;} } </style>
<div> <div class="box-b" style="margin-left:5vw;">If your browser does not support row-gap, the text and border will be red.</div> </div> <style> .box-b {border: 0.5vw solid blue; color: blue;} @supports not(row-gap: 1vw) { .box-a {border: 0.5vw solid red; color: red;} } </style>
<div> <div class="box-c" style="margin-left:5vw;">If your browser supports display: grid and shape-outside: circle(), the text and border will be red. </div> </div> <style> .box-c {border: 0.5vw solid blue; color: blue;} @supports (display: grid) and (shape-outside:circle()){ .box-c {border: 0.5vw solid red; color: red;} } </style>
<div class="wrapper"> <div class="box-1">Box 1<br>Has more content <br>than the other boxes.</div> <div class="box-2">Box 2</div> <div class="box-3">Box 3</div> </div> <style> .box-1 {margin-left:5vw; float: left; width: 30%; border: .2vw solid rgb(95, 97, 110); border-radius: .5vw; padding: 1vw;} @supports (display: grid) { .wrapper {display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 1vw;} .box-1 {width: auto;} } </style>
Container queries allow you to query a parent element's size and style to determine the styles which should be applied to any of its children.
If, for example, a container has less space available in the surrounding context, you can hide certain elements or use smaller fonts.
Container queries are an alternative to media queries, which apply styles to elements based on viewport size or other device characteristics. Media queries can only access and leverage information from the viewport, which means they can only work on a macro view of a page layout.
Container queries are a more precise tool that can support any number of layouts or layouts within layouts.
To use container queries, you need to declare a containment context on an element so that the browser knows you might want to query the dimensions of this container later. To do this, use the container-type property with a value of "size", "inline-size", or "normal".
These values have the following effects:
size : the query will be based on the inline and block dimensions of the container. Applies layout, style, and size containment to the container.
inline-size : the query will be based on the inline dimensions of the container. Applies layout, style, and inline-size containment to the element.
normal : the element is not a query container for any container size queries, but remains a query container for container style queries.
<div class="post"> <div class="card"> <h4>Card title</h4> <p>Card content</p> </div> </div> <style> .post {container-type: inline-size;} /* Default heading styles for the card title */ .card h4 {font-size: 1em; } /* If the container is larger than 700px */ @container (min-width: 700px) { .card h2 {font-size: 2em;} } </style>
It's also possible to give a containment context a name using the "container-name" property. Once named, the name can be used in a "@container query" so as to target a specific container.
<div class="post"> <div class="card"> <h4>Card title</h4> <p>Card content</p> </div> </div> <style> .post {container-type: inline-size; container-name: sidebar;} @container sidebar (min-width: 700px) { .card {font-size: 2em;} } </style>
The shorthand way of declaring a containment context is to use the container property:
.post{ container: sidebar / inline-size;}
These specify a length relative to the dimensions of a query container. Components that use units of length relative to their container are more flexible to use in different containers without having to recalculate concrete length values.
The container query length units are:
cqw : 1% of a query container's width.
cqh : 1% of a query container's height.
cqi : 1% of a query container's inline size.
cqb: 1% of a query container's block size.
cqmin: the smaller value of either cqi or cqb.
cqmax: the larger value of either cqi or cqb.
For browsers that don't yet support container queries, grid and flex can be used to create a similar effect for the card component used on this page.
<div class="card-container"> <div class="card-child"> <div class="image"> <img src="../pics/2018-Sh-04.jpg" alt=""> </div> <div class="meta"> <h4>Shanghai trip!</h4> <i>June 1, 2023</i> <p>There is a lot to say and write about this metropole, but words are arguably not enough to describe and depict the amazing facts in this city.</p> </div> </div> </div> <style> .card-container {container: card / inline-size;} .card-child {display: grid; grid-template-columns: 1fr 1fr; } .card-child h4 {font-size: clamp(1vw, 7cqi, 4vw);} @container (max-width: 45vw) { .card-child {grid-template-columns: 1fr;} .meta {padding: 1vw;} img {aspect-ratio: 16 / 9;} } @layer base { .card-container {background: #ffe4e8; overflow: hidden; resize: horizontal; width: 25vw; max-width: 40vw; min-width: 15vw;} .meta {padding: 2vw;} img {width: 100%; height: 100%; aspect-ratio: 1/1; object-fit: cover; object-position: 20% 20%;} } </style>